﻿using SketchUpAPI.NET.Enums;
using SketchUpAPI.NET.SketchUp.Exception;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace SketchUpAPI.NET.Objects.Tables
{
    /// <summary>
    /// 管理 <see cref="SketchUp.SketchUpModel"/> 的 <see cref="Layer"/> 和 <see cref="LayerFolder"/>
    /// </summary>
    /// <remarks>
    /// 注意：该类型并非 SketchUpAPI 接口中存在的类型，而是该 API 为方便管理组件定义而创建的类型。该类型的 Id 使用的是 <see cref="SketchUp.SketchUpModel"/> 的 Id
    /// </remarks>
    public class LayerTable : ObjectBase
    {
        #region API 函数
        /// <summary>
        /// 获取图层个数
        /// </summary>
        /// <param name="model"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetNumLayers(IntPtr model, out int count);

        /// <summary>
        /// 获取全部图层
        /// </summary>
        /// <param name="model"></param>
        /// <param name="len"></param>
        /// <param name="layers"><see cref="Layer"/>[]</param>
        /// <param name="realcount"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetLayers(IntPtr model, int len, IntPtr[] layers, out int realcount);

        /// <summary>
        /// 添加图层
        /// </summary>
        /// <param name="model"></param>
        /// <param name="len"></param>
        /// <param name="layers"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelAddLayers(IntPtr model, int len, IntPtr[] layers);

        /// <summary>
        /// 获取默认图层
        /// </summary>
        /// <param name="model"></param>
        /// <param name="layer"><see cref="Layer"/></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetDefaultLayer(IntPtr model, out IntPtr layer);

        /// <summary>
        /// 删除图层
        /// </summary>
        /// <remarks>删除图层后，该图层中的物体将被移动到默认图层；默认图层不能被删除</remarks>
        /// <param name="model"></param>
        /// <param name="len"></param>
        /// <param name="layers"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelRemoveLayers(IntPtr model, int len, IntPtr[] layers);

        /// <summary>
        /// 获取当前图层
        /// </summary>
        /// <param name="model"></param>
        /// <param name="layer"><see cref="Layer"/></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetActiveLayer(IntPtr model, out IntPtr layer);

        /// <summary>
        /// 获取当前图层
        /// </summary>
        /// <param name="model"></param>
        /// <param name="layer"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelSetActiveLayer(IntPtr model, IntPtr layer);

        /// <summary>
        /// 图层文件夹个数
        /// </summary>
        /// <param name="model"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetNumLayerFolders(IntPtr model, out int count);

        /// <summary>
        /// 获取所有图层文件夹
        /// </summary>
        /// <param name="model"></param>
        /// <param name="len"></param>
        /// <param name="layer_folders"><see cref="LayerFolder"/>[]</param>
        /// <param name="realcount"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetLayerFolders(IntPtr model, int len, IntPtr[] layer_folders, out int realcount);

        /// <summary>
        /// 删除空的图层文件夹
        /// </summary>
        /// <param name="model"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelPurgeEmptyLayerFolders(IntPtr model, out int count);

        /// <summary>
        /// 添加图层文件夹
        /// </summary>
        /// <param name="model"></param>
        /// <param name="layer_folder"><see cref="LayerFolder"/></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelAddLayerFolder(IntPtr model, IntPtr layer_folder);

        /// <summary>
        /// 删除未使用的图层
        /// </summary>
        /// <param name="model"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelPurgeUnusedLayers(IntPtr model, out int count);

        /// <summary>
        /// 获取顶级图层的个数
        /// </summary>
        /// <remarks>顶级图层，既不属于图层文件夹的图层</remarks>
        /// <param name="model"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetNumTopLevelLayers(IntPtr model, out int count);

        /// <summary>
        /// 获取顶级图层
        /// </summary>
        /// <param name="model"></param>
        /// <param name="len"></param>
        /// <param name="layers"><see cref="Layer"/>[]</param>
        /// <param name="realcount"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetTopLevelLayers(IntPtr model, int len, IntPtr[] layers, out int realcount);

        /// <summary>
        /// 删除图层文件夹
        /// </summary>
        /// <param name="model"></param>
        /// <param name="len"></param>
        /// <param name="layer_folders"><see cref="LayerFolder"/>[]</param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelRemoveLayerFolders(IntPtr model, int len, IntPtr[] layer_folders);
        #endregion

        /// <summary>
        /// 图层文件夹的个数
        /// </summary>
        public int LayerFolderCount
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetNumLayerFolders(Id, out int c));
                return c;
            }
        }

        /// <summary>
        /// 获取图层文件夹
        /// </summary>
        public List<LayerFolder> LayerFolders
        {
            get
            {
                IntPtr[] pts = new IntPtr[LayerFolderCount];
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetLayerFolders(Id, pts.Length, pts, out _));
                return pts.Select(i => new LayerFolder(i)).ToList();
            }
        }

        /// <summary>
        /// 默认图层
        /// </summary>
        public Layer DefaultLayer
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetDefaultLayer(Id, out IntPtr l));
                return new Layer(l);
            }
        }

        /// <summary>
        /// 图层个数
        /// </summary>
        public int LayerCount
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetNumLayers(Id, out int c));
                return c;
            }
        }

        /// <summary>
        /// 所有图层
        /// </summary>
        public List<Layer> Layers
        {
            get
            {
                IntPtr[] pts = new IntPtr[LayerCount];
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetLayers(Id, pts.Length, pts, out int realcount));
                return pts.Select(i => new Layer(i)).ToList();
            }
        }

        /// <summary>
        /// 获取顶级图层
        /// </summary>
        public List<Layer> TopLevelLayers
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetNumTopLevelLayers(Id, out int c));
                IntPtr[] pts = new IntPtr[c];
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetTopLevelLayers(Id, c, pts, out _));
                return pts.Select(i => new Layer(i)).ToList();
            }
        }

        /// <summary>
        /// 当前图层
        /// </summary>
        public Layer ActiveLayer
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetActiveLayer(Id, out IntPtr l));
                return new Layer(l);
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SUModelSetActiveLayer(Id, value.Id));
            }
        }

        internal LayerTable(IntPtr id) => Id = id;

        /// <summary>
        /// 添加图层
        /// </summary>
        /// <param name="layers"></param>
        public void Add(params Layer[] layers)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUModelAddLayers(Id, layers.Length, layers.Select(l => l.Id).ToArray()));
        }

        /// <summary>
        /// 添加图层文件夹
        /// </summary>
        /// <param name="layerFolder"></param>
        public void Add(LayerFolder layerFolder)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUModelAddLayerFolder(Id, layerFolder.Id));
        }

        /// <summary>
        /// 删除图层
        /// </summary>
        /// <remarks>删除图层后，该图层中的物体将被移动到默认图层；默认图层不能被删除</remarks>
        /// <param name="layers"></param>
        public void Remove(params Layer[] layers)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUModelRemoveLayers(Id, layers.Length, layers.Select(l => l.Id).ToArray()));
        }

        /// <summary>
        /// 删除图层文件夹
        /// </summary>
        /// <param name="layerFolders"></param>
        public void Remove(params LayerFolder[] layerFolders)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUModelRemoveLayerFolders(Id, layerFolders.Length, layerFolders.Select(l => l.Id).ToArray()));
        }

        /// <summary>
        /// 删除空的图层文件夹
        /// </summary>
        /// <returns>删除的个数</returns>
        public int RemoveEmptyLayerFolders()
        {
            SketchUpExceptionHelper.ThrowSUResult(SUModelPurgeEmptyLayerFolders(Id, out int count));
            return count;
        }

        /// <summary>
        /// 删除未使用的图层
        /// </summary>
        /// <returns>删除的个数</returns>
        public int RemoveEmptyLayers()
        {
            SketchUpExceptionHelper.ThrowSUResult(SUModelPurgeUnusedLayers(Id, out int count));
            return count;
        }
    }
}